/**
* @file gui_message.h
* @brief message define and function
* @details 
* @author huangbin
* @version V1.0.0
* @date 2025-06-12
* @copyright All documents are copyrighted by Shenzhen Xinlongwei Technology Co., LTD.
*            They may not be used for commercial purposes without permission
*/

#ifndef __GUI_MESSAGE_H__
#define __GUI_MESSAGE_H__

/*============================ INCLUDES ======================================*/
#include "../gui_cfg.h"

#include "arm_2d.h"
#include "arm_2d_helper.h"

#ifdef   __cplusplus
extern "C" {
#endif

#if defined(__clang__)
#   pragma clang diagnostic push
#   pragma clang diagnostic ignored "-Wmissing-declarations"
#   pragma clang diagnostic ignored "-Wmicrosoft-anon-tag"
#   pragma clang diagnostic ignored "-Wpadded"
#endif

/*============================ MACROS ========================================*/

/* OOC header, please DO NOT modify  */
#ifdef __GUI_MESSAGE_IMPLEMENT__
#   undef   __GUI_MESSAGE_IMPLEMENT__
#   define  __ARM_2D_IMPL__
#elif defined(__GUI_MESSAGE_INHERIT__)
#   undef   __GUI_MESSAGE_INHERIT__
#   define __ARM_2D_INHERIT__
#endif
#include "arm_2d_utils.h"

/*============================ MACROFIED FUNCTIONS ===========================*/
/*============================ TYPES =========================================*/

enum {
    GUI_KEY_NONE = 0,                       

};


enum {
        GUI_MSG_INVALID                     = 0x00,

    __GUI_MSG_WIDGETS_EVT_MSK               = 0xF0,
    __GUI_MSG_WIDGETS_EVT                   = 0x80,
        GUI_MSG_WIDGETS_EVT_ON_LOAD         = __GUI_MSG_WIDGETS_EVT,
        GUI_MSG_WIDGETS_EVT_ON_DEPOSE,
        GUI_MSG_WIDGETS_EVT_UPDATE,
        GUI_MSG_WIDGETS_EVT_UPDATE_TREE,
        GUI_MSG_WIDGETS_EVT_REFRESH,
        GUI_MSG_WIDGETS_EVT_POST_REFRESH,
        GUI_MSG_WIDGETS_EVT_GET_ACTIVE,
        GUI_MSG_WIDGETS_EVT_LOST_ACTIVE,
        GUI_MSG_WIDGETS_EVT_TIMER,
        GUI_MSG_WIDGETS_EVT_COMM,
    
    //! All control specific events share the same code region (0x90~0x9F)
    __GUI_MSG_WIDGETS_SPECIFIC_EVT_MSK      = 0xF0,
    __GUI_MSG_WIDGETS_SPECIFIC_EVT          = 0x90,


    __GUI_MSG_POINTER_EVT_MSK               = 0xF0,
    __GUI_MSG_POINTER_EVT                   = 0xA0,
        GUI_MSG_POINTER_EVT_DOWN            = __GUI_MSG_POINTER_EVT,
        GUI_MSG_POINTER_EVT_HOLD,
        GUI_MSG_POINTER_EVT_UP,
        GUI_MSG_POINTER_EVT_CLICK,
        GUI_MSG_POINTER_EVT_LONG_PRESSING,
        GUI_MSG_POINTER_EVT_DOUBLE_CLICK,

        GUI_MSG_POINTER_EVT_MOVE_IN,
        GUI_MSG_POINTER_EVT_MOVE_OUT,
        GUI_MSG_POINTER_EVT_HOVER,
        GUI_MSG_POINTER_EVT_MOVE,

    __GUI_MSG_KEY_EVT_MSK                   = 0xF0,
    __GUI_MSG_KEY_EVT                       = 0xB0,
        GUI_MSG_KEY_EVT_DOWN                = __GUI_MSG_KEY_EVT,
        GUI_MSG_KEY_EVT_REPEAT,
        GUI_MSG_KEY_EVT_UP,
        GUI_MSG_KEY_EVT_PRESSED,
        GUI_MSG_KEY_EVT_LONG_PRESSING,
        GUI_MSG_KEY_EVT_DOUBLE_PRESSED,
    
    __GUI_MSG_GESTURE_EVT_MSK               = 0xF0,
    __GUI_MSG_GESTURE_EVT                   = 0xC0,
        GUI_MSG_GESTURE_EVT_SLIDE           = __GUI_MSG_GESTURE_EVT,
        GUI_MSG_GESTURE_EVT_WHEEL,                                  /* mouse wheel */
        GUI_MSG_GESTURE_EVT_ZOOM_IN,
        GUI_MSG_GESTURE_EVT_ZOOM_OUT,
        GUI_MSG_GESTURE_EVT_ROTATE_CLOCKWISE,
        GUI_MSG_GESTURE_EVT_ROTATE_ANTICLOCKWISE,

};

typedef struct gui_msg_core_t {
    struct gui_msg_core_t   *ptNext;

    void                    *ptTargetWidget;

ARM_PROTECTED(
    uint32_t u8ID           : 8;            /*!< GUI_MSG_xxxx */
    uint32_t bFromPool      : 1;            /*!< created from pool or heap */
    uint32_t bFromHeap      : 1;            /*!< created from heap */
    uint32_t                : 6;            /*!< reserved */
    uint32_t u16Key         : 16;           /* key for validation */
)

} gui_msg_core_t;

typedef struct gui_msg_refresh_t {
    implement(gui_msg_core_t);

    arm_2d_region_t *ptRegionOnScreen;
} gui_msg_refresh_t;

typedef struct gui_msg_key_evt_t {
    implement(gui_msg_core_t);
    uint16_t hwKeyValue;
    int16_t iLastPeriodInMS;
} gui_msg_key_evt_t;

typedef struct gui_msg_pointer_evt_t {
    implement(gui_msg_core_t);
    uint16_t hwIndex;                   /*!< the poiner index */
    uint16_t hwPeriodInMs;

    implement(arm_2d_location_t);
} gui_msg_pointer_evt_t;

typedef struct gui_msg_gesture_evt_t {
    implement(gui_msg_core_t);

    implement(arm_2d_region_t);
    uint16_t hwInMS;
    uint8_t chIndex;                            /*!< finger/pointer index */
} gui_msg_gesture_evt_t;

typedef struct gui_msg_timer_evt_t {
    implement(gui_msg_core_t);
    uint8_t chIndex;                            /*!< timer index */
} gui_msg_timer_evt_t;

typedef struct gui_msg_communication_evt_t {
    implement(gui_msg_core_t);
    uint8_t chCmdCode;                            /*!< command code */
    uint32_t wParameter;                            /*!< command Parameter */
} gui_msg_communication_evt_t;

typedef union gui_msg_t {
    implement(gui_msg_core_t);

    gui_msg_pointer_evt_t tPointerEvent;
    gui_msg_key_evt_t     tKeyEvent;
    gui_msg_gesture_evt_t tGestureEvent;
	gui_msg_timer_evt_t   tTimerEvent;
	gui_msg_communication_evt_t tCommEvent;
	
    gui_msg_refresh_t     tRefreshRequest;
} gui_msg_t;

typedef struct gui_helper_msg_fifo_t {

ARM_PRIVATE(
    gui_msg_core_t *ptHead;
    gui_msg_core_t *ptTail;
)

} gui_helper_msg_fifo_t;


typedef struct gui_helper_msg_pool_cfg_t {
    bool bAllowUsingHeap;
} gui_helper_msg_pool_cfg_t;
typedef struct gui_helper_msg_pool_t {
ARM_PRIVATE(
    gui_msg_t  *ptFreeList;
    gui_helper_msg_pool_cfg_t tCFG;
)
} gui_helper_msg_pool_t;


typedef gui_msg_core_t *gui_i_msg_read_handler_t(void *pObj);

typedef struct gui_i_msg_read_t {
    gui_i_msg_read_handler_t *fnRead;
    void *pTarget;
} gui_i_msg_read_t;

typedef struct gui_i_msg_frontend_t {
    gui_i_msg_read_handler_t *fnRead;
} gui_i_msg_frontend_t;


typedef struct gui_msg_frontend_t gui_msg_frontend_t;

typedef enum {
    GUI_FRONTEND_PROCESS_MODE_ALL,
    GUI_FRONTEND_PROCESS_MODE_NON_CRITICAL,
    GUI_FRONTEND_PROCESS_MODE_CRITICAL,
} gui_msg_frontend_process_mode_t;

typedef enum {
    GUI_FRONTEND_GENERIC,
    GUI_FRONTEND_KEY,
    GUI_FRONTEND_POINTER,
} gui_msg_frontend_type_t;

struct gui_msg_frontend_t {
ARM_PROTECTED(
    struct gui_msg_frontend_t *ptNext;

    struct {
        gui_i_msg_read_t tIn;
    } Dependency;

    const gui_i_msg_frontend_t *ptChain;

    gui_helper_msg_fifo_t       tOutputFIFO;

    gui_helper_msg_pool_t *ptPool;

    arm_fsm_rt_t (*fnProcess)(gui_msg_frontend_t *ptThis,
                              gui_msg_frontend_process_mode_t tMode);
)
};

typedef struct gui_msg_frontend_chain_t {
    gui_msg_frontend_t *ptHead;
    gui_msg_frontend_t *ptTail;

    gui_msg_frontend_t *ptCurrent;
} gui_msg_frontend_chain_t;

typedef struct gui_helper_msg_cfg_t {
    bool bAllowUsingHeap;
} gui_helper_msg_cfg_t;

typedef struct gui_helper_msg_t {

ARM_PROTECTED(

    gui_helper_msg_pool_t tPool;
    gui_helper_msg_cfg_t tCFG;
    
    struct {
        gui_msg_frontend_chain_t tChain;
        gui_helper_msg_fifo_t tFIFO;
    } KeyPipe;

    struct {
        gui_msg_frontend_chain_t tChain;
        gui_helper_msg_fifo_t tFIFO;
    } PointerPipe;

    struct {
        gui_msg_frontend_chain_t tChain;
        gui_helper_msg_fifo_t tFIFO;
    } MainPipe;

    uint8_t  chPT;
    uint8_t  bIsComplete    : 1;
    uint8_t  bIsWorking     : 1;
    uint8_t  bFIFOEmpty     : 1;
    uint8_t                 : 6;
    uint16_t                : 16;
)

} gui_helper_msg_t;

/*============================ GLOBAL VARIABLES ==============================*/
/*============================ PROTOTYPES ====================================*/

ARM_PUBLIC_METHOD(

   /*------------------------------------------------------------------------*
    * Message Helper                                                         *
    *------------------------------------------------------------------------*/
    extern
    ARM_NONNULL(1)
    void gui_helper_msg_init(gui_helper_msg_t *ptThis, gui_helper_msg_cfg_t *ptCFG);

    extern
    ARM_NONNULL(1)
    gui_msg_core_t *gui_helper_msg_item_init(gui_msg_core_t *ptItem);

    extern
    ARM_NONNULL(1)
    gui_msg_core_t *gui_helper_msg_item_set_id(gui_msg_core_t *ptItem, uint8_t chID);

    extern
    ARM_NONNULL(1)
    uint_fast8_t gui_helper_msg_item_get_id(gui_msg_core_t *ptItem);

    extern
    ARM_NONNULL(1,2)
    void gui_helper_msg_add_items_to_pool(  gui_helper_msg_t *ptThis, 
                                            gui_msg_t *ptItems, 
                                            uint_fast16_t hwCount);
    extern
    ARM_NONNULL(1)
    gui_msg_t *gui_helper_msg_new(gui_helper_msg_t *ptThis);

    extern
    ARM_NONNULL(1,2)
    void gui_helper_msg_send(gui_helper_msg_t *ptThis, gui_msg_core_t *ptMSG);

    extern
    ARM_NONNULL(1, 2)
    bool gui_helper_msg_frontend_register(  
                                        gui_helper_msg_t *ptThis, 
                                        gui_msg_frontend_t *ptFrontend,
                                        gui_msg_frontend_type_t tType);
    
    extern
    ARM_NONNULL(1)
    arm_fsm_rt_t gui_helper_msg_task(gui_helper_msg_t *ptThis);

    extern
    ARM_NONNULL(1)
    bool gui_helper_msg_send_key_event( gui_helper_msg_t *ptThis,
                                        uint8_t chKeyEvent,
                                        uint16_t hwKeyValue,
                                        void *pTargetWidget);
    
    extern
    ARM_NONNULL(1)
    bool gui_helper_msg_send_pointer_event( gui_helper_msg_t *ptThis,
                                            uint8_t chPointerEvent,
                                            uint16_t hwPointerIndex,
                                            int16_t iX,
                                            int16_t iY,
                                            void *pTargetWidget);
    
    extern
    ARM_NONNULL(1)
    const char *gui_helper_msg_get_name(gui_msg_core_t *ptMSG);
)


ARM_PROTECTED_METHOD(

   /*------------------------------------------------------------------------*
    * Message POOL                                                           *
    *------------------------------------------------------------------------*/
    extern
    ARM_NONNULL(1)
    gui_helper_msg_pool_t *gui_helper_msg_pool_init(
                                        gui_helper_msg_pool_t *ptThis,
                                        gui_helper_msg_pool_cfg_t *ptCFG);

    extern
    ARM_NONNULL(1,2)
    void gui_helper_msg_pool_add_items( gui_helper_msg_pool_t *ptThis, 
                                        gui_msg_t *ptItems, 
                                        uint_fast16_t hwCount);

    extern
    ARM_NONNULL(1)
    gui_msg_t *gui_helper_msg_pool_new(gui_helper_msg_pool_t *ptThis);

    extern
    ARM_NONNULL(1)
    gui_msg_core_t * gui_helper_msg_pool_free(  gui_helper_msg_pool_t *ptThis, 
                                                gui_msg_t *ptItem);

   /*------------------------------------------------------------------------*
    * Message FIFO                                                           *
    *------------------------------------------------------------------------*/

    extern
    ARM_NONNULL(1)
    gui_helper_msg_fifo_t *gui_helper_msg_fifo_init(
                                                gui_helper_msg_fifo_t *ptThis);

    extern
    ARM_NONNULL(1,2)
    void gui_helper_msg_fifo_append(gui_helper_msg_fifo_t *ptThis, 
                                    gui_msg_core_t *ptMSG);

    extern
    ARM_NONNULL(1)
    gui_msg_core_t *gui_helper_msg_fifo_peek(gui_helper_msg_fifo_t *ptThis);

    extern
    ARM_NONNULL(1)
    gui_msg_core_t *gui_helper_msg_fifo_get(gui_helper_msg_fifo_t *ptThis);

    extern
    ARM_NONNULL(1)
    gui_msg_core_t *gui_helper_msg_peek(gui_helper_msg_t *ptThis);

    extern
    ARM_NONNULL(1)
    bool gui_helper_msg_fifo_is_empty(gui_helper_msg_fifo_t *ptThis);


   /*------------------------------------------------------------------------*
    * Message Helper                                                         *
    *------------------------------------------------------------------------*/
    extern
    ARM_NONNULL(1)
    gui_msg_core_t *gui_helper_msg_get(gui_helper_msg_t *ptThis);

    extern
    ARM_NONNULL(1)
    gui_msg_core_t * gui_helper_msg_free(   gui_helper_msg_t *ptThis,
                                            gui_msg_t *ptItem);
)


/*============================ INCLUDES ======================================*/
#include "./msg_frontend/gui_frontend.h"


#if defined(__clang__)
#   pragma clang diagnostic pop
#endif

#ifdef   __cplusplus
}
#endif

#endif
